Shell学习笔记11-for和select循环语句

GO


for循环语句和while循环语句类似,但for循环语句主要用于执行次数有限的循环,而不是用于守护进程及无限循环。for循环语句常见的语法有两种,下面将在不同的语法中对for循环语句进行详尽的讲解。

1. for循环语法结构

第一种for循环语句为变量取值型,语法结构如下:

1
2
3
4
for 变量名 in 变量取值列表
do
指令...
done

提示:在此结构中,in 变量取值列表可以省略,省略时相当于in "$@",特就是使用for i就相当于使用for i in "$@"

在这种for循环语句语法中,for关键字后面会有一个变量名,变量名依次获取in关键字后面的变量取值列表内容(以空格分隔),每次仅取一个,然后进入循环(do和done之间的部分)执行循环内的所有指令,当执行到done时结束本次循环。之后,变量名再继续获取变量列表里的下一个变量值,继续执行循环内的所有指令,当执行到done时结束返回,以此类推,知道取完变量列表里的最后一个值并进入循环执行到done结束为止。

第二种for循环语句称为C语言型for循环语句,其语法结构如下:

1
2
3
4
for ((exp1; exp2; exp3))
do
指令...
done

说明:此种循环语句和while循环语句类似,但语法结构比while循环更规范、工整。

for关键字后的双括号内是三个表达式,第一个是变量初始化(例如:i=0),第二个为变量的范围(例如:i<100),第三个为变量自增或自减(例如:i++)。当第一个表达式的初始化值符合第二个变量的范围时,就进入循环执行;当条件不满足时就退出循环。

范例:for循环和while循环对比

  • for版

    1
    2
    3
    4
    for ((i=1; i<=3; i++))
    do
    echo $i
    done
  • 转化为while版

    1
    2
    3
    4
    5
    6
    i=1
    while ((i<=3))
    do
    echo $i
    ((i++))
    done

特别说明:

  • 如果希望程序持续运行,则多用while,包括守护进程。
  • 如果是有限次循环,则多用for,实际工作中使用for的机会更多。

2. for循环语句的基础实践

下面是几个for循环语句的示例:

  • 范例1:竖向打印5、4、3、2、1这个5个数字

    • 参考答案1:直接列出元素的方法:

      1
      2
      3
      4
      for num in 5 4 3 2 1
      do
      echo $num
      done
    • 参考答案2:利用大括号{}生成数字序列的方法

      1
      2
      3
      4
      for num in {5..1}
      do
      echo $num
      done
    • 参考答案3:采用seq生产数字序列的用法

      1
      2
      3
      4
      for num in `seq 5 -1 1`
      do
      echo $num
      done
  • 范例2:获取当前目录下的目录或文件名,并将其作为变量列表打印输出

    1
    2
    3
    4
    5
    cd /test
    for filename in `ls`
    do
    echo $filename
    done
  • 范例3:用for循环批量修改文件扩展名(把txt改成jpg)

    1
    2
    3
    4
    5
    6
    #!/bin/bash
    cd /test
    for filename in `ls | grep "txt$"`
    do
    mv $filename `echo $filename | cut -d . -f1`.gif
    done
    • 本题还有更简单的实现方法,即通过rename命令来直接实现,如下:
      1
      2
      cd /test
      rename "gif" "txt" *.gif

3. for循环语句的企业级案例

范例1:在Linux下批量修改文件名,将文件中的_finished去掉。

  • 提示:通过此题的解答可以学习到sed、awk、rename、mv等命令的实战应用
  • 参考答案1:采用Shell脚本、for循环加sed的方法

    1
    2
    3
    4
    5
    6
    #!/bin/sh
    cd /theshu
    for file in `ls *.jpg`
    do
    mv $file `echo $file | sed 's/_finished//g'`
    done
  • 参考答案2:使用ls结合awk实现,这个方法中没有for循环,但它可以在很多场景中替换for循环(下例是:给文件名加上”_finished”):(注意是对文件名的修改,而不是字符串的修改)

    1
    ls | awk -F "." '{print "mv",$0,$1"_finished."$2}' | bash
  • 参考答案3:通过专业的改名命令rename来实现:

    1
    rename "_finished" "" *.jpg

范例2:在生产环境下,批量去掉测试数据所用的bd字符:

  • 实现命令如下:rename "bd" "" *.html

4. select循环语句介绍及语法

打印菜单可以用cat方法(被称为here文档),其实还有另外一种实现菜单的方法,即通过select循环语句实现。

select循环语句的主要作用可能就是创建菜单,在执行带select循环语句的脚本时,输出会按照数字顺序的列表显示一个菜单项,并显示提示符(默认是#?),同时等待用户输入数字进行选择。一下就是关于select的知识。

第一种for循环语句为变量取值型,语法结构如下:

1
2
3
4
select 变量名 [ in 菜单取值列表 ]
do
指令...
done

在这种select循环语句的语法中,在执行脚本后,select关键字后面会有一个变量名,变量名依次获取in关键字后面的变量取值列表内容(以空格分隔),每次仅取一个,然后进入循环(do和done之间),执行循环内的所有指令,当执行到done时结束返回,之后变量名再继续取变量列表里的下一个变量值,继续执行循环内的所有指令,当执行到done时结束为止。与for循环不同的是,select循环执行后会出现菜单项等待用户选择(不会自动循环所有变量列表),而用户输入的只能是菜单项前面的数字序号,每输入一次对应的序号就会执行一次循环,直到变量后面对应列表取完为止。

5. select循环语句案例

范例:用select循环打印简单菜单项的多种实现方法

  • 方法1:直接使用列表字符串

    • 脚本开发

      1
      2
      3
      4
      5
      #!/bin/bash
      select name in theshu theshan wang
      do
      echo $name
      done
    • 执行结果如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      [root@theshu ~]# sh select1.sh
      1) theshu
      2) theshan
      3) thewang
      #? 1
      theshu
      #? 2
      theshan
      #? 3
      thewang
      #? 4 #<==输入错误则返回空
      #?
  • 方法2:采用数组做变量列表

    1
    2
    3
    4
    5
    6
    #!/bin/bash
    array=(theshu theshan thewang)
    select name in "${array[@]}"
    do
    echo $name
    done
  • 方法3:把命令结果作为变量列表(菜单项)

    • 数据准备

      1
      2
      3
      4
      5
      6
      7
      [root@theshu ~]# mkdir -p /tmp/test
      [root@theshu ~]# mkdir -p /tmp/test/{theshu,theshan,thewang}
      [root@theshu ~]# ls -l /tmp/test/
      total 12
      drwxr-xr-x 2 root root 4096 Mar 1 10:29 theshan
      drwxr-xr-x 2 root root 4096 Mar 1 10:29 theshu
      drwxr-xr-x 2 root root 4096 Mar 1 10:29 thewang
    • 脚本开发

      1
      2
      3
      4
      5
      #!/bin/bash
      select name in `ls /tmp/test`
      do
      echo $name
      done
    • 执行结果

      1
      2
      3
      4
      1) theshan
      2) theshu
      3) thewang
      #?

OK

0%